﻿#include "../include/header/cat-config.hpp"
#include "../include/cat-signal.hpp"
#include "../include/cat-window.hpp"
#include "../include/cat.hpp"

#include <WinUser.h>

#include "../include/util/concurrentqueue.h"

static moodycamel::ConcurrentQueue<unsigned int> *q=nullptr;

static inline moodycamel::ConcurrentQueue<unsigned int>* getSignalQue() {
    if (!q) 
    {
        q = new moodycamel::ConcurrentQueue<unsigned int>();
    }
    return q;
}

static inline bool cat_peek_signal(unsigned int &signal, unsigned int low, unsigned int high) {
    for (unsigned int i = low; i != high + 1;i++) {
        if (getSignalQue()->try_dequeue(i)) {
            signal = i;
            return true;
        }
    }
    return false;
}

void on_signal(cat_window_t* _window)
{
    unsigned int signal = 0;
    while (cat_peek_signal(signal, UIWM_UPDATE, UIWM_DOCKINGTOOLWINDOW))
        switch (signal)
        {
            case UIWM_UPDATE:
            {
                update_config_from_buffer_config();

                int modeid = cat_get_curent_mode_id();
                cat_update_mode(modeid);        
                cat_update_input();
                cat_update_ui();
                cat_update_output();
                break;
            }              
            case UIWM_RELOAD:
            {
                cat_release_mode(cat_get_curent_mode_id());

                update_config_from_buffer_config(); 

                cat_init_mode(cat_get_curent_mode_id());

                cat_data_t* config = cat_load_default_config();
                _window->window->setSize(sf::Vector2u(config->json["decoration"]["window_size"][0].asInt(), config->json["decoration"]["window_size"][1].asInt()));
                break;
            }           
            case UIWM_MODECHANGE:
            {
                cat_release_mode(cat_get_curent_mode_id());

                update_config_from_buffer_config();

                cat_init_mode(cat_get_curent_mode_id());

                cat_data_t* config = cat_load_default_config();
                _window->window->setSize(sf::Vector2u(config->json["decoration"]["window_size"][0].asInt(), config->json["decoration"]["window_size"][1].asInt()));
                break;
            }  
            case UIWM_BAKECOLORCHANGE:
            {
                update_config_from_buffer_config();
                break;
            }
            case UIWM_WINDOWCHANGE:
            {
                update_config_from_buffer_config();
                cat_set_gui_visible(true);
                cat_updata_window(_window);

                int modeid = cat_get_curent_mode_id();
                cat_update_mode(modeid);
                cat_update_input();
                cat_update_ui();
                cat_update_output();

                break;
            }
            case UIWM_WINDOWRESIZE:
            {
                cat_data_t* config = cat_load_default_config();
                cat_resize_window(_window,config->json["main_decoration"]["window_size"][0].asInt(),config->json["main_decoration"]["window_size"][1].asInt());

                sf::FloatRect visibleArea(0, 0, config->json["decoration"]["window_size"][0].asInt(), config->json["decoration"]["window_size"][1].asInt());
                _window->window->setView(sf::View(visibleArea));
                break;
            }
            case UIWM_WINDOWSHOULDCLOSE:
            {
                cat_shatdown_gui();
                break;
            }
            case UIWM_DOCKINGTOOLWINDOW:
            {
#ifdef _WIN32
                DWORD father = GetWindowLong((HWND)cat_get_handle(), GWL_STYLE);
                ::SetWindowLong((HWND)cat_get_handle(), GWL_STYLE, father | WS_CLIPCHILDREN);
                HWND hFindWnd = (HWND)cat_get_buffer_window_handle();
                if (hFindWnd)
                {
                    long dwStyle = GetWindowLong(hFindWnd, GWL_STYLE);
                    dwStyle |= WS_CHILD;
                    ::SetWindowLong(hFindWnd, GWL_STYLE, dwStyle);
                    ::SetParent(hFindWnd, (HWND)cat_get_handle());
                    RECT rtClient;
                    GetClientRect(hFindWnd, &rtClient);
                    ::MoveWindow(hFindWnd, rtClient.left, rtClient.top, rtClient.right, rtClient.bottom, TRUE);
                }
#endif // _WIN32
                break;
            }
        }
}

void cat_push_signal(unsigned int _signal)
{
    getSignalQue()->enqueue(_signal);
}

